/*
 * This file is part of aion-engine <aion-engine.net>
 *
 * aion-engine is private software: you can redistribute it and or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Private Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * aion-engine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License
 * along with aion-engine.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.network.aion.clientpackets;

import com.aionengine.gameserver.dataholders.DataManager;
import com.aionengine.gameserver.model.gameobjects.Pet;
import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.model.items.storage.StorageType;
import com.aionengine.gameserver.model.templates.windstreams.Location2D;
import com.aionengine.gameserver.model.templates.windstreams.WindstreamTemplate;
import com.aionengine.gameserver.network.aion.AionClientPacket;
import com.aionengine.gameserver.network.aion.AionConnection.State;
import com.aionengine.gameserver.network.aion.serverpackets.*;
import com.aionengine.gameserver.questEngine.QuestEngine;
import com.aionengine.gameserver.questEngine.model.QuestEnv;
import com.aionengine.gameserver.services.SerialKillerService;
import com.aionengine.gameserver.services.SiegeService;
import com.aionengine.gameserver.services.TownService;
import com.aionengine.gameserver.services.WeatherService;
import com.aionengine.gameserver.services.rift.RiftInformer;
import com.aionengine.gameserver.spawnengine.InstanceRiftSpawnManager;
import com.aionengine.gameserver.world.World;
import com.aionengine.gameserver.world.WorldMapType;

/**
 * Client is saying that level[map] is ready.
 *
 * @author -Nemesiss-
 * @author Kwazar
 * @modify xXMashUpXx
 */
public class CM_LEVEL_READY extends AionClientPacket {

    public CM_LEVEL_READY(int opcode, State state, State... restStates) {
        super(opcode, state, restStates);
    }

    @Override
    protected void readImpl() {
    }

    @Override
    protected void runImpl() {
        Player activePlayer = getConnection().getActivePlayer();

        if (activePlayer.getHouseRegistry() != null)
            sendPacket(new SM_HOUSE_OBJECTS(activePlayer));
        if (activePlayer.isInInstance()) {
            sendPacket(new SM_INSTANCE_COUNT_INFO(activePlayer.getWorldId(), activePlayer.getInstanceId()));
        }
        sendPacket(new SM_PLAYER_INFO(activePlayer, false));
        activePlayer.getController().startProtectionActiveTask();
        sendPacket(new SM_MOTION(activePlayer.getObjectId(), activePlayer.getMotions().getActiveMotions()));

        WindstreamTemplate template = DataManager.WINDSTREAM_DATA.getStreamTemplate(activePlayer.getPosition().getMapId());
        Location2D location;
        if (template != null)
            for (int i = 0; i < template.getLocations().getLocation().size(); i++) {
                location = template.getLocations().getLocation().get(i);
                sendPacket(new SM_WINDSTREAM_ANNOUNCE(location.getFlyPathType().getId(), template.getMapid(), location.getId(),
                        location.getState()));
            }
        location = null;
        template = null;

        /**
         * Spawn player into the world.
         */
        // If already spawned, despawn before spawning into the world
        if (activePlayer.isSpawned())
            World.getInstance().despawn(activePlayer);
        World.getInstance().spawn(activePlayer);

        activePlayer.getController().refreshZoneImpl();
        
        // because fortress buff should only be avaible in fortress locations
        SiegeService.getInstance().fortressBuffRemove(activePlayer);

        // SM_SHIELD_EFFECT, SM_ABYSS_ARTIFACT_INFO3
        if (activePlayer.isInSiegeWorld()) {
            SiegeService.getInstance().onEnterSiegeWorld(activePlayer);
        }

        // SM_SERIAL_KILLER
        SerialKillerService.getInstance().onEnterMap(activePlayer);

        // SM_RIFT_ANNOUNCE
        RiftInformer.sendRiftsInfo(activePlayer);
        InstanceRiftSpawnManager.sendInstanceRiftStatus(activePlayer);

        // SM_NEARBY_QUESTS
        activePlayer.getController().updateNearbyQuests();

        /**
         * Loading weather for the player's region
         */
        WeatherService.getInstance().loadWeather(activePlayer);

        QuestEngine.getInstance().onEnterWorld(new QuestEnv(null, activePlayer, 0, 0));

        activePlayer.getController().onEnterWorld();

        // zone channel message (is this must be here?)
        if (!WorldMapType.getWorld(activePlayer.getWorldId()).isPersonal())
            sendPacket(new SM_SYSTEM_MESSAGE(1390122, activePlayer.getPosition().getInstanceId()));
        
        
        activePlayer.getEffectController().updatePlayerEffectIcons();
        sendPacket(SM_CUBE_UPDATE.cubeSize(StorageType.CUBE, activePlayer));

        Pet pet = activePlayer.getPet();
        if (pet != null && !pet.isSpawned())
            World.getInstance().spawn(pet);
        activePlayer.setPortAnimation(0);

        TownService.getInstance().onEnterWorld(activePlayer);
    }

}